﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
//using System.Collections;

namespace GIFT2
{
    public partial class NuevoFormulario : Form
    {
        ControlFormulario controlFormulario;  //Cambio
        public NuevoFormulario(InterfazFormulario interfaz)
        {
            controlFormulario = new ControlFormulario(); //Cambio
            ctrlkeyPresionada = false;
            seleccionMultiple = new ArrayList();
            miInterfaz = interfaz;
            InitializeComponent();
            this.Closing += new CancelEventHandler(NuevoFormulario_Closing);
            this.Resize += new EventHandler(NuevoFormulario_Resize);
            this.Shown += new EventHandler(NuevoFormulario_Shown); //CAMBIO
        }


        void NuevoFormulario_Shown(object sender, EventArgs e)
        {
            cargaComponentes();
           // MessageBox.Show(" size: " + this.Controls[0].Size, "antes de entrar");
        }

        void NuevoFormulario_Closing(object sender, CancelEventArgs e)
        {
            miInterfaz.setFormularioActivo(false);
            //MessageBox.Show(" size: "+this.Controls[0].Size,"antes de salir");
        }

        void NuevoFormulario_Resize(object sender, EventArgs e)
        {
            panel.Size = new Size(this.Size.Width, this.Size.Height);
            miInterfaz.setSize(this.Size.Width, this.Size.Height);
        }

        public void setIcono(Icon miIcono) 
        {
            this.Icon = miIcono;
        }

        public void setTitulo(string titulo) 
        {
            this.Text = titulo;
        }

        public void setSize (int x, int y)
        {
            this.Size = new Size(y, x);
            panel.Size = new System.Drawing.Size(y, x);
        }

        public Point getPunto() 
        {
            Point vacio = new Point(0, 0);
            if (punto.IsEmpty) { return vacio; }
            else { return punto; }
        }

        public void agregarControl(Control micontrol) 
        {
            micontrol.MouseDown += new MouseEventHandler(c_MouseDown);
            micontrol.ContextMenuStrip = contextMenuStrip1;
            this.panel.Controls.Add(micontrol);
        }

        private void c_MouseDown(object sender, MouseEventArgs e)
        {
            Control c = sender as Control;
            this.ActiveControl = c;
            if (e.Button == MouseButtons.Right) { } // se necesita para que pueda aparecer el menu con click derecho
            else
            {
                if ((ctrlkeyPresionada) && (c != null)) //si ctrl + click se selecciona el componente
                {
                    //agrega el componente a la lista de seleccion si no ha sido agregado
                    if (!seleccionMultiple.Contains(c))
                    {
                        c.BackColor = Color.LightBlue;//backColor
                        seleccionMultiple.Add(c);
                    }
                    //si ya existia entonces lo saca de la seleccion
                    else
                    {
                        seleccionMultiple.Remove(c);
                        c.BackColor = Color.LightGray; //LE TENGO QEU DEVOLVER EL COLOR ORIGINAL...
                    }
                }
                else//si ctrl no esta presionado
                {
                    //si el componente no esta dentro de la seleccion deshace toda la seleccion o sea que blanquea la coleccion
                    if (!seleccionMultiple.Contains(c))//puede ser qeu no estuviera en la seleccion xq no habia seleccion
                    {
                        if (!(seleccionMultiple.Count == 0))
                        {
                            for (int i = 0; i <= (seleccionMultiple.Count - 1); ++i)
                            {
                                ((Control)seleccionMultiple[i]).BackColor = Color.LightGray;
                            }
                            seleccionMultiple.Clear();
                        }
                        c.DoDragDrop(c, DragDropEffects.Move);//si no hay seleccion mueve componente
                    }
                    else //si el componente es parte de la seleccion arrastra a todos juntos
                    {
                        dragDropMultiple(c);
                    }
                }
            }
            ctrlkeyPresionada = false; //esto no es necesario xq lo hace el evento keydown
        }
        private void dragDropMultiple(Control c) //arrastra c y los elementos de la seleccion a la que pertenece el control c
        {
            Point inicio = new Point(0, 0);
            Point final = new Point(0, 0);
            Point diferencia = new Point(0, 0);
            Point actualControl = new Point(0, 0);
            inicio = c.Location;
            c.DoDragDrop(c, DragDropEffects.Move);
            final = c.Location;
            diferencia.X = (final.X - inicio.X);
            diferencia.Y = (final.Y - inicio.Y);
            for (int i = 0; i <= (seleccionMultiple.Count - 1); ++i)
            {
                if (c != (Control)seleccionMultiple[i])
                {
                    actualControl = ((Control)seleccionMultiple[i]).Location;
                    actualControl.X = (actualControl.X + diferencia.X);
                    actualControl.Y = (actualControl.Y + diferencia.Y);
                    ((Control)seleccionMultiple[i]).Location = new System.Drawing.Point(actualControl.X, actualControl.Y);
                }
            }
        }
        private void NuevoFormulario_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control)
            {
                ctrlkeyPresionada = true;
            }
        }

        private void NuevoFormulario_KeyUp(object sender, KeyEventArgs e)
        {
            if (ctrlkeyPresionada == true)
            {
                ctrlkeyPresionada = false;
            }
        }                
        private void panel_DragDrop(object sender, DragEventArgs e)
        {
            Control c = e.Data.GetData(e.Data.GetFormats()[0]) as Control;
            if (c != null)
            {
                c.Location = this.panel.PointToClient(new Point(e.X, e.Y));
                this.panel.Controls.Add(c);
                miInterfaz.cambioPunto(c);
            }
        }

        private void panel_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        private void eliminarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("¿Está seguro que desea eliminar el componente del formulario?", "Eliminar", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                miInterfaz.eliminaComponente(ActiveControl.Name);
                panel.Controls.Remove(this.ActiveControl);
            }
        }

        //metodo nuevo, para el resize de componentes
        private void resizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Control c = ActiveControl;
            c.SizeChanged += new EventHandler(c_SizeChanged);            
            CambiarEstilo(c);
        }

        //por los momentos para que actualize la bd
        private void c_SizeChanged(object sender, EventArgs e)
        {
            ConsultasFormularios consulta = new ConsultasFormularios();
            Control c = ActiveControl;
            
            //MessageBox.Show("c.text: " + c.Name+" this.text: " +this.Text+ " c.h: " + c.Height+ " c.w: " + c.Width);
            consulta.cambiaTamanyoComponente(c.Name,this.Text,""+c.Height,""+c.Width);
        }

        //nuevo, cambia el estilo del control para que se pueda redimensionar
        private void CambiarEstilo(Control aControl)
        {
            //Hacer este control redimensionable, usando el API
            //Pone o quita el estilo dimensionable
            int Style;
            //
            // Si se produce un error, no hacer nada...
            try
            {
                Style = GetWindowLong(aControl.Handle.ToInt32(), GWL_STYLE);
                if ((Style & WS_THICKFRAME) == WS_THICKFRAME) // & = And
                {
                    // Si ya lo tiene, lo quita
                    Style = Style ^ WS_THICKFRAME; // ^ = Xor
                }
                else
                {
                    // Si no lo tiene, lo pone
                    Style = Style | WS_THICKFRAME; // | = Or
                }
                SetWindowLong(aControl.Handle.ToInt32(), GWL_STYLE, Style);
                SetWindowPos(aControl.Handle.ToInt32(), this.Handle.ToInt32(), 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_DRAWFRAME);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                MessageBox.Show("El control " + aControl.Name + " no permite que se redimensione","",MessageBoxButtons.OK ,MessageBoxIcon.Warning  );
            }
        }

        public void buscaElimina(string nombre)
        {
            foreach (Control ctl in panel.Controls)
            {
                if (ctl.Name.Equals(nombre))
                {
                    panel.Controls.Remove(ctl);
                }
            }
        }

        //NUEVO//////
        private void cargaComponentes()
        {
            Control micontrol = null;
            ArrayList listaComponentes = new ArrayList();
            listaComponentes = controlFormulario.obtieneComponentes(this.Text);
            if (listaComponentes != null)
            {
                for (int i = 0; i < listaComponentes.Count; ++i)
                {
                    ArrayList comp;
                    comp = (ArrayList)listaComponentes[i];

                    switch (comp[9].ToString())
                    {
                        case (""):
                            Label label = new Label();
                            label.AutoSize = true;
                            label.Name = comp[0].ToString();
                            label.Text = comp[0].ToString();
                            label.AutoSize = true;
                            label.Location = new Point(Convert.ToInt32(comp[3].ToString()), Convert.ToInt32(comp[4].ToString()));
                            label.ForeColor = System.Drawing.Color.FromName(comp[8].ToString());
                            String nombreFuente = comp[5].ToString();
                            int tamañoFuente = Convert.ToInt32(comp[6].ToString());
                            label.Font = new Font(nombreFuente, tamañoFuente);
                            String estilo = comp[7].ToString();
                            FontStyle fontStyle = label.Font.Style;
                            if (estilo.Contains("Bold"))
                            {
                                fontStyle |= FontStyle.Bold;
                            }
                            if (estilo.Contains("Italic"))
                            {
                                fontStyle |= FontStyle.Italic;
                            }
                            if (estilo.Contains("Strikeout"))
                            {
                                fontStyle |= FontStyle.Strikeout;
                            }
                            if (estilo.ToString().Contains("Underline"))
                            {
                                fontStyle |= FontStyle.Underline;
                            }
                            label.Font = new Font(label.Font, fontStyle);
                            micontrol = label;
                            break;
                        case ("texto"):
                            TextBox texto = new TextBox();
                            texto.Location = new Point(Convert.ToInt32(comp[3].ToString()), Convert.ToInt32(comp[4].ToString()));
                           // texto.Size = new Size(Convert.ToInt32(comp[1].ToString()), Convert.ToInt32(comp[2].ToString()));
                            texto.Width = Convert.ToInt32(comp[1].ToString());
                            texto.Height = Convert.ToInt32(comp[2].ToString());
                            texto.AutoSize = false;
                            micontrol.AutoSize = false;
                            texto.Name = comp[0].ToString();
                            //recupero a traves de una serie de consultas el campo por defecto correspondiente
                            String idTipoCampo = controlFormulario.obtieneAtributoEspecificoComponenteFormulario(texto.Name, "[id tipo campo]", this.Text);
                            String idTipo = controlFormulario.obtieneAtributoEspecificoTabla("Tipo Campo Componente", "id texto", "id", idTipoCampo);
                            String campoDefecto = controlFormulario.obtieneAtributoEspecificoTabla("texto", "texto por defecto", "correlativo", idTipo);
                            texto.Text = campoDefecto;
                            micontrol = texto;
                            break;
                        case ("lista"):
                            ListBox lista = new ListBox();
                            lista.Location = new Point(Convert.ToInt32(comp[3].ToString()), Convert.ToInt32(comp[4].ToString()));
                            lista.Name = comp[0].ToString();
                            //recupero a traves de una serie de consultas el nombre de la lista
                            idTipoCampo = controlFormulario.obtieneAtributoEspecificoComponenteFormulario(lista.Name, "[id tipo campo]", this.Text);
                            idTipo = controlFormulario.obtieneAtributoEspecificoTabla("Tipo Campo Componente", "id lista", "id", idTipoCampo);
                            String nombreLista = controlFormulario.obtieneAtributoEspecificoTabla("lista", "nombre", "correlativo", idTipo);
                            ArrayList terminos = controlFormulario.obtieneTerminosLista(nombreLista);
                            for (int k = 0; k < terminos.Count; ++k)
                            {
                                lista.Items.Add(terminos[k].ToString());
                            }
                            micontrol = lista;
                            break;
                        case "fechaHora":
                            DateTimePicker fecha = new DateTimePicker();
                            fecha.Format = System.Windows.Forms.DateTimePickerFormat.Short;
                            fecha.Location = new Point(Convert.ToInt32(comp[3].ToString()), Convert.ToInt32(comp[4].ToString()));
                            fecha.Name = comp[0].ToString();
                            fecha.Size = new System.Drawing.Size(130, 20);
                            //se recuperan los ids, hasta llegar a la fecha por defecto que se encuentra en la bd
                            idTipoCampo = controlFormulario.obtieneAtributoEspecificoComponenteFormulario(fecha.Name, "[id tipo campo]", this.Text);
                            idTipo = controlFormulario.obtieneAtributoEspecificoTabla("Tipo Campo Componente", "id fechaHora", "id", idTipoCampo);
                            campoDefecto = controlFormulario.obtieneAtributoEspecificoTabla("fechaHora", "fecha por defecto", "correlativo", idTipo);
                            fecha.Text = campoDefecto;
                            micontrol = fecha;
                            break;
                        case "incremental":
                            NumericUpDown incremental = new NumericUpDown();
                            incremental.Location = new Point(Convert.ToInt32(comp[3].ToString()), Convert.ToInt32(comp[4].ToString()));
                            incremental.Name = comp[0].ToString();
                            //se recuperan los ids, hasta llegar al incremental, y sacar el valor inicial
                            idTipoCampo = controlFormulario.obtieneAtributoEspecificoComponenteFormulario(incremental.Name, "[id tipo campo]", this.Text);
                            idTipo = controlFormulario.obtieneAtributoEspecificoTabla("Tipo Campo Componente", "id incremental", "id", idTipoCampo);
                            campoDefecto = controlFormulario.obtieneAtributoEspecificoTabla("incremental", "valor inicial", "correlativo", idTipo);
                            incremental.Text = campoDefecto;
                            micontrol = incremental;
                            break;
                        case "binario":
                            RadioButton binario = new RadioButton();
                            binario.Location = new Point(Convert.ToInt32(comp[3].ToString()), Convert.ToInt32(comp[4].ToString()));
                            binario.Name = comp[0].ToString();
                            binario.Text = comp[0].ToString();
                            //se recuperan los ids, hasta llegar al binario, y sacar el valor por defecto
                            idTipoCampo = controlFormulario.obtieneAtributoEspecificoComponenteFormulario(binario.Name, "[id tipo campo]", this.Text);
                            idTipo = controlFormulario.obtieneAtributoEspecificoTabla("Tipo Campo Componente", "id binario", "id", idTipoCampo);
                            campoDefecto = controlFormulario.obtieneAtributoEspecificoTabla("binario", "valor por defecto", "correlativo", idTipo);
                            binario.Checked = int.Parse(campoDefecto) == 1 ? true : false;//pregunta si el valor es uno, si es checa el combo, de otra manera lo pone en false
                            micontrol = binario;
                            panel.Controls.Remove(micontrol);
                            break;
                        case "numero":
                            TextBox numero = new TextBox();
                            numero.Location = new Point(Convert.ToInt32(comp[3].ToString()), Convert.ToInt32(comp[4].ToString()));
                            numero.Name = comp[0].ToString();
                            //se recuperan los ids, hasta llegar al numero, y sacar el valor por defecto
                            idTipoCampo = controlFormulario.obtieneAtributoEspecificoComponenteFormulario(numero.Name, "[id tipo campo]", this.Text);
                            idTipo = controlFormulario.obtieneAtributoEspecificoTabla("Tipo Campo Componente", "id numero", "id", idTipoCampo);
                            campoDefecto = controlFormulario.obtieneAtributoEspecificoTabla("numero", "valor por defecto", "correlativo", idTipo);
                            numero.Text = campoDefecto;
                            micontrol = numero;
                            break;
                        case "jerarquia":
                            TreeView jerarquia = new TreeView();
                            jerarquia.Location = new Point(Convert.ToInt32(comp[3].ToString()), Convert.ToInt32(comp[4].ToString()));
                            jerarquia.Name = comp[0].ToString();
                            micontrol = jerarquia;
                            break;
                    }
                    if (micontrol != null)
                    {
                        agregarControl(micontrol);
                    }
                }
            }
        }
        //nuevo
        /***********************VARIABLES PARA REDIMENSIONAR COMPONENTES*********************************/
        //Declaraciones del API para 32 bits
        [DllImport("user32.DLL", EntryPoint = "GetWindowLong")]
        static extern int GetWindowLong(
            int hWnd,   // manejador de ventana
            int nIndex  // valor del desplazamiento
        );
        [DllImport("user32.DLL", EntryPoint = "SetWindowLong")]
        static extern int SetWindowLong(
            int hWnd,       // manejador de ventana
            int nIndex,     // valor del desplazamiento a asignar
            int dwNewLong   // valor nuevo
        );
        [DllImport("user32.DLL", EntryPoint = "SetWindowPos")]
        static extern bool SetWindowPos(
            int hWnd,               // manejador de ventana
            int hWndInsertAfter,    // controlador del orden de desplazamiento
            int X,                  // posicion horizontal
            int Y,                  // posicion vertical
            int cx,                 // ancho (width)
            int cy,                 // altura (height)
            uint uFlags             // opciones de la posicion
        );
        // Constantes para usar con el API
        const int GWL_STYLE = (-16);
        const int WS_THICKFRAME = 0x40000; // Con borde redimensionable
        //
        const int SWP_DRAWFRAME = 0x20;
        const int SWP_NOMOVE = 0x2;
        const int SWP_NOSIZE = 0x1;
        const int SWP_NOZORDER = 0x4;
        //mantiene el valor de true cuando la tecla ctrl esta abajo, si se suelta se le asigna valor false.
        private bool ctrlkeyPresionada;

        //coleccion de los componentes de form que han sido seleccionados con ctrl+click
        // private ControlCollection seleccionMultiple ;//inicializado en el constructor de esta clase
        private ArrayList seleccionMultiple;

    }//Fin de clase
}

